package org.wattdepot.cli.command;

import java.util.List;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.cli.processor.CommandLineInterface;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.resource.sensordata.jaxb.SensorData;
import org.wattdepot.resource.property.jaxb.Property;
import org.wattdepot.resource.source.jaxb.Source;
import org.wattdepot.util.tstamp.Tstamp;

/**
 * Creates a listing all of the sensor data instances for the specified day. Displays the source's
 * output, in MegaWatts, throughout a specified day also including the source's tool. This class
 * extends CommandLineInterface to have access to the WattDepotClient and implements
 * WattDepotCliCommand interface to ensure this class does a specific command.
 * 
 * @author Edward Meyer, Bao Huy Ung
 */
public class DailySensorData extends CommandLineInterface implements WattDepotCliCommand {

  /**
   * Constructor to create an object ListSensorDay to list all sensor data instances for a specific
   * source throughout a specified day.
   */
  public DailySensorData() {
    // Empty constructor.
  }

  /**
   * Returns a listing all of the sensor data instances for the specified day. Displays the source's
   * output, in MegaWatts, throughout a specified day also including the source's tool.
   * 
   * @param args Is a list of all the arguments entered by the user.
   * @return A string listing all sensor data, or an error message.
   */
  public String doCommand(List<String> args) {
    // If there are too few or too many arguments, return an error message.
    if (args.size() != 4) {
      return "Error: Incorrect number of arguments were entered. Expected 4, instead "
          + args.size() + " were entered.";
    }

    String inputSourceName = args.get(1);
    String inputStamp = args.get(3);
    XMLGregorianCalendar timeStamp = null;
    Source printSource = null;

    // String variable that will hold all the information.
    StringBuffer output = new StringBuffer(200);

    // Check if a valid source was entered.
    printSource = isValidSource(inputSourceName);
    if (printSource == null) {
      return "\"" + inputSourceName + "\" is not a valid source.";
    }

    // Check if keyword "day" was entered in the command.
    if (!args.get(2).equalsIgnoreCase("day")) {
      return "Error: Keyword \"day\" was mistyped as \"" + args.get(2) + "\".";
    }

    // Attempt to parse the entered timestamp to see if it's a valid timestamp.
    timeStamp = isValidTimestamp(inputStamp);
    if (timeStamp == null) {
      return "Timestamp: \"" + inputStamp + "\" cannot be parsed into a timestamp.";
    }

    // Create a list of all sensor data throughout the day of a given source.
    List<SensorData> sensorData = null;

    // Check to see if there is data for the given day.
    try {
      sensorData =
      // Increment the timeStamp by 1 to get all activity until the next day.
          client.getSensorDatas(inputSourceName, timeStamp, Tstamp.incrementDays(timeStamp, 1));
    }
    catch (ResourceNotFoundException r) {
      return "No sensor data found for \"" + inputSourceName + "\" on timestamp: " + "\""
          + timeStamp.toString() + "\"";
    }
    catch (MiscClientException mce) {
      return "Network communication failure when retrieving sensor data.";
    }
    // If any unknown error occurred.
    catch (Exception e) {
      return "An error occured when retrieving sensor data.\n" + e;
    }

    // Remove the last element in the list since it will dip into the next day.
    if (sensorData.isEmpty()) {
      return "Source: \"" + inputSourceName + "\" contains no sensor data " + "on day: \""
          + inputStamp + "\"";
    }
    sensorData.remove(sensorData.size() - 1);

    // For all activities print the time, tool, and property.
    for (SensorData outputData : sensorData) {
      output.append(outputData.getTimestamp());
      output.append(" Tool: ");
      output.append(outputData.getTool());
      output.append(" Properties: ");
      // Check if the given source has properties.
      if (printSource.isSetProperties()) {
        // Print every property of the given source.
        for (Property property : outputData.getProperties().getProperty()) {
          output.append('(');
          output.append(property.getKey());
          output.append(" : ");
          // Convert to megawatts.
          output.append((Double.parseDouble(property.getValue()) / 1000000.0));
          output.append(" MW)");
        }
        output.append(cr);
      }
      else {
        // Source had no properties.
        output.append("None");
      }
    }
    return output.toString();
  }

}